# 导入 Django 的模型模块
from django.contrib.messages.context_processors import messages
from django.db import models
# 导入 Django 内置的用户模型
from django.contrib.auth.models import User
from django.utils.safestring import mark_safe
from django.utils.text import Truncator
import math
from markdown import markdown


# 定义一个名为 Board 的模型，继承自 models.Model
class Board(models.Model):
    # 定义一个名为 name 的字段，类型为 CharField，最大长度为 30，且必须唯一
    # objects = None
    name = models.CharField(max_length=30, unique=True)
    # 定义一个名为 description 的字段，类型为 CharField，最大长度为 100
    description = models.CharField(max_length=100)

    # __str__ 方法返回对象的字符串表示，用于在 Django 的管理界面中显示对象的名称
    def __str__(self):
        return self.name

    def get_posts_count(self):
        """
        返回版块下的帖子数量。
        """
        return Post.objects.filter(topic__board=self).count()

    def get_last_post(self):
        """
        返回版块下的最后一篇帖子。
        """
        return Post.objects.filter(topic__board=self).order_by('-created_at').first()

# 定义一个名为 Topic 的模型，继承自 models.Model
class Topic(models.Model):
    # 定义一个名为 subject 的字段，类型为 CharField，最大长度为 255
    subject = models.CharField(max_length=255)
    # 定义一个名为 last_updated 的字段，类型为 DateTimeField，自动设置为创建时的时间
    last_updated = models.DateTimeField(auto_now_add=True)
    # 定义一个外键字段，关联到 Board 模型，related_name='topics' 表示反向查询时使用的名称
    board = models.ForeignKey(Board, related_name='topics')
    # 定义一个外键字段，关联到 User 模型，related_name='topics' 表示反向查询时使用的名称
    starter = models.ForeignKey(User, related_name='topics')
    # 定义一个名为views的字段，用于存储正面的浏览次数或点击量
    # 字段类型为PositiveIntegerField，表示只能存储非负整数
    # 默认值设置为0，表示在没有浏览时的初始值为0
    views = models.PositiveIntegerField(default=0)

    def __str__(self):
        # 重写 __str__ 方法，返回对象的字符串表示，这里返回主题的标题
        return self.subject

    def get_page_count(self):
        # 计算并返回主题的页面数
        # 每页显示20个帖子，通过帖子总数除以20并向上取整得到页面数
        count = self.posts.count()
        pages = count / 20
        return math.ceil(pages)

    def has_many_pages(self, count=None):
        # 判断主题是否有多个页面
        # 如果页面数大于6，则认为有很多页面，返回True，否则返回False
        if count is None:
            count = self.get_page_count()
        return count > 6

    def get_page_range(self):
        # 获取主题的页面范围
        # 如果页面数很多，只返回前4个页面的范围；否则返回所有页面的范围
        count = self.get_page_count()
        if self.has_many_pages(count):
            return range(1, 5)
        return range(1, count + 1)

    def get_last_ten_posts(self):
        # 获取主题的最后10个帖子
        # 按创建时间降序排序帖子，并限制结果集大小为10
        return self.posts.order_by('-created_at')[:10]

# 定义一个名为 Post 的模型，继承自 models.Model
class Post(models.Model):
    # 定义一个名为 message 的字段，类型为 TextField，最大长度为 4000
    message = models.TextField(max_length=4000)
    # 定义一个外键字段，关联到 Topic 模型，related_name='posts' 表示反向查询时使用的名称
    topic = models.ForeignKey(Topic, related_name='posts')
    # 定义一个名为 created_at 的字段，类型为 DateTimeField，自动设置为创建时的时间
    created_at = models.DateTimeField(auto_now_add=True)
    # 定义一个名为 updated_at 的字段，类型为 DateTimeField，允许为空
    updated_at = models.DateTimeField(null=True)
    # 定义一个外键字段，关联到 User 模型，related_name='posts' 表示反向查询时使用的名称
    created_by = models.ForeignKey(User, related_name='posts')
    # 定义一个外键字段，关联到 User 模型，允许为空，related_name='+' 表示不创建反向关系
    updated_by = models.ForeignKey(User, null=True, related_name='+')

    def __str__(self):
        """
        重写 __str__ 方法，返回对象的字符串表示，用于在 Django 的管理界面中显示对象的名称。
        如果 message 长度超过 30 个字符，则使用 Truncator 截断并返回前 30 个字符；否则直接返回 message。
        """
        truncated_messages = Truncator(self.message)
        return truncated_messages.chars(30)

    def get_message_as_markdown(self):
        """
        返回帖子的消息内容，使用 markdown 语法进行格式化。
        """
        return mark_safe(markdown(self.message, safe_mode='escape'))


# class Topic(models.Model):
#     """
#     Topic类继承自models.Model，代表一个话题模型。
#     属性:
#     - last_updated: DateTimeField类型，自动设置为实例第一次创建时的当前时间，用于跟踪话题的最后更新时间。
#     """
#     last_updated = models.DateTimeField(auto_now_add=True)
#
# class Past(models.Model):
#     """
#     Past类继承自models.Model，代表一个过去事件的模型。
#     属性:
#     - updated_by: ForeignKey类型，关联到User模型，可以为空，用于记录更新该事件的用户。
#       related_name='+' 表示不创建反向关系，避免自动创建到User模型的反向关联，保持模型定义的灵活性和清晰度。
#     """
#     updated_by = models.ForeignKey(User, null=True, related_name='+')
#
